
package com.learning.rpc.rpc.proxy;

import com.learning.rpc.rpc.Invocation;
import com.learning.rpc.rpc.Invoker;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * ClassName: InvokerInvocationHandler
 * Description: InvocationHandler 实现类
 * Date: 2022/5/10 22:23 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
public class InvokerInvocationHandler implements InvocationHandler {
    private final Invoker invoker;

    public InvokerInvocationHandler(Invoker handler) {
        this.invoker = handler;
    }

    /**
     * 代理访问，向远程调用
     *
     * @param proxy  被代理对象
     * @param method 代理方法 method
     * @param args   参数
     * @return Object
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (method.getDeclaringClass() == Object.class) {
            return method.invoke(invoker, args);
        }
        String methodName = method.getName();
        Class<?>[] parameterTypes = method.getParameterTypes();
        // 不需要远程调用
        if (parameterTypes.length == 0) {
            if ("toString".equals(methodName)) {
                return invoker.toString();
            } else if ("$destroy".equals(methodName)) {
                return null;
            } else if ("hashCode".equals(methodName)) {
                return invoker.hashCode();
            }
        } else if (parameterTypes.length == 1 && "equals".equals(methodName)) {
            return invoker.equals(args[0]);
        }

        // 远程调用
        Invocation invocation = new Invocation();
        invocation.setMethodName(methodName);
        invocation.setArguments(args);
        invocation.setParameterTypes(parameterTypes);
        invocation.setServiceName(method.getDeclaringClass().getName());
        return invoker.invoke(invocation);
    }
}
